package com.roobo.hardware;

import com.roobo.common.utils.Utils;

import android.annotation.SuppressLint;
import android.hardware.roobo.IKeyEventListener;
import android.hardware.roobo.IKeyEventService;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
//import android.os.ServiceManager;
import android.util.ArrayMap;
import android.util.Log;
import android.view.KeyEvent;


/*
 * Created by weidu on 16-11-10.
 */

@SuppressLint("NewApi") public class KeyEventManager {
    private static final String TAG = "KeyEventManager";

    /*
     * 头部触摸
     */
    public static final int KEY_KEYCODE_HEAD = KeyEvent.KEYCODE_F1;
    /*
     * 左边触摸
     */
    public static final int KEY_KEYCODE_LEFT = KeyEvent.KEYCODE_F2;
    /*
     * 右边触摸
     */
    public static final int KEY_KEYCODE_RIGHT = KeyEvent.KEYCODE_F3;
    public static final int KEY_KEYCODE_FUNCTION = KeyEvent.KEYCODE_F4;

    public static final int KEY_KEYCODE_HALL = KeyEvent.KEYCODE_F5;

    public static final int KEY_KEYCODE_RECOVERY = KeyEvent.KEYCODE_F6;

    public static final int KEY_KEYCODE_VOLUME_UP = KeyEvent.KEYCODE_F7;
    public static final int KEY_KEYCODE_VOLUME_DOWN = KeyEvent.KEYCODE_F8;

    private static KeyEventManager sInstance = null;
    private IKeyEventService mService = null;

    private final ArrayMap<KeyEvent.Callback, Handler> mCallbackMap =
            new ArrayMap<KeyEvent.Callback, Handler>();
    private KeyEventListener mKeyEventListener;

    private final Object mLock = new Object();

    private KeyEvent.DispatcherState mKeyDispatchState = new KeyEvent.DispatcherState();

    /*
     * @hide
     */
    private KeyEventManager() {
        //IBinder binder = ServiceManager.getService("keyEventService");
        IBinder binder = Utils.getSystemServiceReflect("keyEventService");
        if (binder == null) {
            throw new UnsupportedOperationException("could not retrieve keyEvent service");
        }
        mService = IKeyEventService.Stub.asInterface(binder);
    }

    public static synchronized KeyEventManager getInstance() {
        if (sInstance == null) {
            sInstance = new KeyEventManager();
        }
        return sInstance;
    }

    public void registerKeyEventListener(KeyEvent.Callback cb, Handler handler) {
        if (handler == null) {
            Looper looper = Looper.myLooper();
            if (looper == null) {
                throw new IllegalArgumentException(
                        "No handler given, and current thread has no looper!");
            }
            handler = new Handler(looper);
        }

        synchronized (mLock) {
            Log.i(TAG, "addTouchEventListener");
            mCallbackMap.put(cb, handler);
        }

        if (mKeyEventListener == null) {
            mKeyEventListener = new KeyEventListener();
            try {
                mService.registerKeyEventListener(mKeyEventListener);
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException in registerKeyEventListener", e);
                mKeyEventListener = null;
            }
        }
    }

    public void unregisterKeyEventListener(KeyEvent.Callback cb) {
        synchronized (mLock) {
            Log.i(TAG, "unregisterKeyEventListener");
            mCallbackMap.remove(cb);
        }

        if (mCallbackMap.isEmpty()) {
            if (mKeyEventListener != null) {
                try {
                    mService.unregisterKeyEventListener(mKeyEventListener);
                } catch (RemoteException e) {
                    Log.e(TAG, "RemoteException in unregisterKeyEventListener", e);
                }
                mKeyEventListener = null;
            }
        }
    }

    /*
     *@param keyCode
     *@return
     *{@link Deprecated}, please use {{@link #getKeyState(RK_KEYS)}
     */
    public boolean getKeyState(int keyCode) {
        try {
            return mService.getKeyState(keyCode);
        } catch (RemoteException e) {
            // TODO: handle exception
        }

        return false;
    }

    public boolean getKeyState(RK_KEYS key) {
        return getKeyState(key.getKeyCode());
    }

    public RK_KEYS getRKKeysByKeyCode(int keycode) {
        for (RK_KEYS keysAttr : RK_KEYS.values()) {
            if (keysAttr.getKeyCode() == keycode) {
                return keysAttr;
            }
        }

        return null;
    }

    private class KeyEventListener extends IKeyEventListener.Stub {

        @Override
        public IBinder asBinder() {
            return this;
        }

        @Override
        public void onKeyEvent(final KeyEvent event) {
            int callbackCount = mCallbackMap.size();
            for (int i = 0; i < callbackCount; i++) {
                Handler handler = mCallbackMap.valueAt(i);
                final KeyEvent.Callback cb = mCallbackMap.keyAt(i);
                handler.post(
                        new Runnable() {
                            @Override
                            public void run() {
                                event.dispatch(cb, mKeyDispatchState, cb);
                            }
                        });
            }
        }
    }

    public enum RK_KEYS {

        head(KeyEvent.KEYCODE_F1, "head"),
        leftear(KeyEvent.KEYCODE_F2, "leftear"),
        rightear(KeyEvent.KEYCODE_F3, "rightear"),
        function(KeyEvent.KEYCODE_F4, "function"),
        hall(KeyEvent.KEYCODE_F5, "hall"),
        recovery(KeyEvent.KEYCODE_F6, "recovery"),
        volumeUp(KeyEvent.KEYCODE_F7, "volumeUp"),
        volumeDown(KeyEvent.KEYCODE_F8, "volumeDown")

        ;
        private final int key_code;
        private final String key_label;
        private RK_KEYS(int code, String label) {
            this.key_code = code;
            this.key_label = label;
        }

        public int getKeyCode() {
            return key_code;
        }

        public String getKeyLabel() {
            return key_label;
        }
    }

}
